using System;
using System.Text;

namespace IQIGame.Onigao.GamePlay
{
    public static class TypeExtends
    {
        public static string GetFullNameWithoutDLL(this Type type)
        {
            string fullName = type.GetCSAliasFullName();
            int cutLen = fullName.IndexOf("[");
            if (cutLen != -1)
            {
                fullName = fullName.Substring(0, cutLen);
            }
            return fullName;
        }

        /// <summary>
        /// 获取类型名，如果类型带有C#别名，则返回别名
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static string GetCSAliasName(this Type type)
        {
            return type switch
            {
                Type _ when type == typeof(int) => "int",
                Type _ when type == typeof(long) => "long",
                Type _ when type == typeof(short) => "short",
                Type _ when type == typeof(byte) => "byte",
                Type _ when type == typeof(float) => "float",
                Type _ when type == typeof(double) => "double",
                Type _ when type == typeof(decimal) => "decimal",
                Type _ when type == typeof(bool) => "bool",
                Type _ when type == typeof(char) => "char",
                Type _ when type == typeof(string) => "string",
                Type _ when type == typeof(object) => "object",
                _ => type.Name // 非别名类型直接返回Name
            };
        }

        /// <summary>
        /// 注意该类不要开放为public
        /// 
        /// 返回全名，如果该类型有C#别名，则返回别名
        /// 不能开放为public是因为该扩展类文件的设计理念不推荐直接使用FullName，因为FullName里面会包含很多+,[],~符号，并不利于直接使用
        /// 如果需要FullName，直接调用type.FullName即可。
        /// 如果需要别名，直接调用type.GetCSAliasName()即可。
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private static string GetCSAliasFullName(this Type type)
        {
            return type switch
            {
                Type _ when type == typeof(int) => "int",
                Type _ when type == typeof(long) => "long",
                Type _ when type == typeof(short) => "short",
                Type _ when type == typeof(byte) => "byte",
                Type _ when type == typeof(float) => "float",
                Type _ when type == typeof(double) => "double",
                Type _ when type == typeof(decimal) => "decimal",
                Type _ when type == typeof(bool) => "bool",
                Type _ when type == typeof(char) => "char",
                Type _ when type == typeof(string) => "string",
                Type _ when type == typeof(object) => "object",
                _ => type.FullName // 非别名类型直接返回FullName
            };
        }

        /// <summary>
        /// 获得全限定名
        /// 但会把内部类前的+替换成. ，并且去掉dll信息，返回标准的全限定名
        /// 并且如果该类型带有泛型，会以标准的泛型命名结尾，例如<int, int>
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static string GetFullyQualifiedName(this Type type)
        {
            return GetFullyQualifiedNameWithGeneric(type);
        }

        private static string GetFullyQualifiedNameWithGeneric(Type type)
        {
            string fullName = type.GetFullNameWithoutDLL().Replace('+', '.');
            if (type.IsGenericType)
            {
                var genericArguments = type.GetGenericArguments();
                var genericArgumentsString = string.Join(", ", Array.ConvertAll(genericArguments, GetFullyQualifiedNameWithGeneric));
                var typeNameWithoutGeneric = fullName.Substring(0, fullName.IndexOf('`'));
                return $"{typeNameWithoutGeneric}<{genericArgumentsString}>";
            }
            else
            {
                return fullName;
            }
        }

        /// <summary>
        /// 获取符合文件命名规范的（比如只能包含字母，数字，下划线等）短限定名
        /// 规则基本和GetFullyQualifiedName一致，但会将.和<>等符号替换为下划线
        /// 短限定名：以.分隔的命名空间和类型，只保留最后几个
        /// </summary>
        /// <param name="type"></param>
        /// <param name="keepPartNum">保留几个部分，例如System.Part1.Part2.Name，如果传2，返回Part2.Name</param>
        /// <returns></returns>
        public static string GetFullyQualifiedNameForFile(this Type type, int keepPartNum)
        {
            if (keepPartNum <= 0)
            {
                return string.Empty;
            }
            string fullName = type.GetFullyQualifiedNameForFile();
            var nameParts = fullName.Split('.');
            if (nameParts.Length <= 1)
            {
                return fullName;
            }
            if (keepPartNum >= nameParts.Length)
            {
                return fullName.Replace(".", "_");
            }
            StringBuilder tempFullName = new StringBuilder();
            for (int i = nameParts.Length - keepPartNum; i < nameParts.Length; i++)
            {
                tempFullName.Append(nameParts[i]);
                if (i < nameParts.Length - 1)
                {
                    tempFullName.Append('_');
                }
            }
            return tempFullName.ToString();
        }

        /// <summary>
        /// 获取符合文件命名规范的（比如只能包含字母，数字，下划线等）全限定名
        /// 规则基本和GetFullyQualifiedName一致，但会将.和<>等符号替换为下划线
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static string GetFullyQualifiedNameForFile(this Type type)
        {
            string fullName = type.GetFullNameWithoutDLL().Replace('+', '.');
            if (type.IsGenericType)
            {
                var genericArguments = type.GetGenericArguments();
                var genericArgumentsString = string.Join("_", Array.ConvertAll(genericArguments, GetFullyQualifiedNameForFile));
                var typeNameWithoutGeneric = fullName.Substring(0, fullName.IndexOf('`'));
                return $"{typeNameWithoutGeneric}_{genericArgumentsString}";
            }
            else
            {
                return fullName;
            }
        }
    }
}
